#include "Precompile.h"
#include "WinMessagesInputSystem.h"

namespace Input{
	WinMessagesInputSystem::WinMessagesInputSystem():m_mouseXPos(0),m_mouseYPos(0){
		// Create translation map
		m_keyTranslateMap[27] = EIK_ESCAPE;
		m_keyTranslateMap[49] = EIK_1;
		m_keyTranslateMap[50] = EIK_2;
		m_keyTranslateMap[51] = EIK_3;
		m_keyTranslateMap[52] = EIK_4;
		m_keyTranslateMap[53] = EIK_5;
		m_keyTranslateMap[54] = EIK_6;
		m_keyTranslateMap[55] = EIK_7;
		m_keyTranslateMap[56] = EIK_8;
		m_keyTranslateMap[57] = EIK_9;
		m_keyTranslateMap[48] = EIK_0;
		m_keyTranslateMap[189] = EIK_MINUS;
		//m_keyTranslateMap[DIK_EQUALS] = EIK_EQUALS;
		m_keyTranslateMap[8] = EIK_BACK;
		m_keyTranslateMap[9] = EIK_TAB;
		m_keyTranslateMap[81] = EIK_Q;
		m_keyTranslateMap[87] = EIK_W;
		m_keyTranslateMap[69] = EIK_E;
		m_keyTranslateMap[82] = EIK_R;
		m_keyTranslateMap[84] = EIK_T;
		m_keyTranslateMap[89] = EIK_Y;
		m_keyTranslateMap[85] = EIK_U;
		m_keyTranslateMap[73] = EIK_I;
		m_keyTranslateMap[79] = EIK_O;
		m_keyTranslateMap[80] = EIK_P;
		//m_keyTranslateMap[DIK_LBRACKET] = EIK_LBRACKET;
		//m_keyTranslateMap[DIK_RBRACKET] = EIK_RBRACKET;
		m_keyTranslateMap[13] = EIK_RETURN;
		m_keyTranslateMap[17] = EIK_LCONTROL;
		m_keyTranslateMap[65] = EIK_A;
		m_keyTranslateMap[83] = EIK_S;
		m_keyTranslateMap[68] = EIK_D;
		m_keyTranslateMap[70] = EIK_F;
		m_keyTranslateMap[71] = EIK_G;
		m_keyTranslateMap[72] = EIK_H;
		m_keyTranslateMap[74] = EIK_J;
		m_keyTranslateMap[75] = EIK_K;
		m_keyTranslateMap[76] = EIK_L;
		//m_keyTranslateMap[DIK_SEMICOLON] = EIK_SEMICOLON;
		//m_keyTranslateMap[DIK_APOSTROPHE] = EIK_APOSTROPHE;
		//m_keyTranslateMap[DIK_GRAVE] = EIK_GRAVE;
		m_keyTranslateMap[16] = EIK_LSHIFT;
		//m_keyTranslateMap[DIK_BACKSLASH] = EIK_BACKSLASH;
		m_keyTranslateMap[90] = EIK_Z;
		m_keyTranslateMap[88] = EIK_X;
		m_keyTranslateMap[67] = EIK_C;
		m_keyTranslateMap[86] = EIK_V;
		m_keyTranslateMap[66] = EIK_B;
		m_keyTranslateMap[78] = EIK_N;
		m_keyTranslateMap[77] = EIK_M;
		m_keyTranslateMap[188] = EIK_COMMA;
		m_keyTranslateMap[190] = EIK_PERIOD;
		m_keyTranslateMap[111] = EIK_SLASH;
		m_keyTranslateMap[16] = EIK_RSHIFT;
		m_keyTranslateMap[106] = EIK_MULTIPLY;
		//m_keyTranslateMap[DIK_LMENU] = EIK_LMENU;
		m_keyTranslateMap[32] = EIK_SPACE;
		m_keyTranslateMap[20] = EIK_CAPITAL;
		m_keyTranslateMap[112] = EIK_F1;
		m_keyTranslateMap[113] = EIK_F2;
		m_keyTranslateMap[114] = EIK_F3;
		m_keyTranslateMap[115] = EIK_F4;
		m_keyTranslateMap[116] = EIK_F5;
		m_keyTranslateMap[117] = EIK_F6;
		m_keyTranslateMap[118] = EIK_F7;
		m_keyTranslateMap[119] = EIK_F8;
		m_keyTranslateMap[120] = EIK_F9;
		//m_keyTranslateMap[DIK_F10] = EIK_F10;
		m_keyTranslateMap[144] = EIK_NUMLOCK;
		//m_keyTranslateMap[DIK_SCROLL] = EIK_SCROLL;
		m_keyTranslateMap[103] = EIK_NUMPAD7;
		m_keyTranslateMap[104] = EIK_NUMPAD8;
		m_keyTranslateMap[105] = EIK_NUMPAD9;
		m_keyTranslateMap[109] = EIK_SUBTRACT;
		m_keyTranslateMap[100] = EIK_NUMPAD4;
		m_keyTranslateMap[101] = EIK_NUMPAD5;
		m_keyTranslateMap[102] = EIK_NUMPAD6;
		m_keyTranslateMap[107] = EIK_ADD;
		m_keyTranslateMap[97] = EIK_NUMPAD1;
		m_keyTranslateMap[98] = EIK_NUMPAD2;
		m_keyTranslateMap[99] = EIK_NUMPAD3;
		m_keyTranslateMap[96] = EIK_NUMPAD0;
		m_keyTranslateMap[110] = EIK_DECIMAL;
		//m_keyTranslateMap[DIK_OEM_102] = EIK_OEM_102;
		m_keyTranslateMap[122] = EIK_F11;
		m_keyTranslateMap[123] = EIK_F12;
		//m_keyTranslateMap[DIK_F13] = EIK_F13;
		//m_keyTranslateMap[DIK_F14] = EIK_F14;
		//m_keyTranslateMap[DIK_F15] = EIK_F15;
		//m_keyTranslateMap[DIK_KANA] = EIK_KANA;
		//m_keyTranslateMap[DIK_ABNT_C1] = EIK_ABNT_C1;
		//m_keyTranslateMap[DIK_CONVERT] = EIK_CONVERT;
		//m_keyTranslateMap[DIK_NOCONVERT] = EIK_NOCONVERT;
		//m_keyTranslateMap[DIK_YEN] = EIK_YEN;
		//m_keyTranslateMap[DIK_ABNT_C2] = EIK_ABNT_C2;
		//m_keyTranslateMap[DIK_NUMPADEQUALS] = EIK_NUMPADEQUALS;
		//m_keyTranslateMap[DIK_PREVTRACK] = EIK_PREVTRACK;
		//m_keyTranslateMap[DIK_AT] = EIK_AT;
		//m_keyTranslateMap[DIK_COLON] = EIK_COLON;
		//m_keyTranslateMap[DIK_UNDERLINE] = EIK_UNDERLINE;
		//m_keyTranslateMap[DIK_KANJI] = EIK_KANJI;
		//m_keyTranslateMap[DIK_STOP] = EIK_STOP;
		//m_keyTranslateMap[DIK_AX] = EIK_AX;
		//m_keyTranslateMap[DIK_UNLABELED] = EIK_UNLABELED;
		//m_keyTranslateMap[DIK_NEXTTRACK] = EIK_NEXTTRACK;
		m_keyTranslateMap[13] = EIK_NUMPADENTER;
		/*m_keyTranslateMap[DIK_RCONTROL] = EIK_RCONTROL;
		m_keyTranslateMap[DIK_MUTE] = EIK_MUTE;
		m_keyTranslateMap[DIK_CALCULATOR] = EIK_CALCULATOR;
		m_keyTranslateMap[DIK_PLAYPAUSE] = EIK_PLAYPAUSE;
		m_keyTranslateMap[DIK_MEDIASTOP] = EIK_MEDIASTOP;
		m_keyTranslateMap[DIK_VOLUMEDOWN] = EIK_VOLUMEDOWN;
		m_keyTranslateMap[DIK_VOLUMEUP] = EIK_VOLUMEUP;
		m_keyTranslateMap[DIK_WEBHOME] = EIK_WEBHOME;
		m_keyTranslateMap[DIK_NUMPADCOMMA] = EIK_NUMPADCOMMA;
		m_keyTranslateMap[DIK_DIVIDE] = EIK_DIVIDE;
		m_keyTranslateMap[DIK_SYSRQ] = EIK_SYSRQ;
		m_keyTranslateMap[DIK_RMENU] = EIK_RMENU;
		m_keyTranslateMap[DIK_PAUSE] = EIK_PAUSE;
		m_keyTranslateMap[DIK_HOME] = EIK_HOME;*/
		m_keyTranslateMap[38] = EIK_UP;
		//m_keyTranslateMap[DIK_PRIOR] = EIK_PRIOR;
		m_keyTranslateMap[37] = EIK_LEFT;
		m_keyTranslateMap[39] = EIK_RIGHT;
		m_keyTranslateMap[35] = EIK_END;
		m_keyTranslateMap[40] = EIK_DOWN;
		//m_keyTranslateMap[DIK_NEXT] = EIK_NEXT;
		m_keyTranslateMap[45] = EIK_INSERT;
		m_keyTranslateMap[46] = EIK_DELETE;
		/*m_keyTranslateMap[DIK_LWIN] = EIK_LWIN;
		m_keyTranslateMap[DIK_RWIN] = EIK_RWIN;
		m_keyTranslateMap[DIK_APPS] = EIK_APPS;
		m_keyTranslateMap[DIK_POWER] = EIK_POWER;
		m_keyTranslateMap[DIK_SLEEP] = EIK_SLEEP;
		m_keyTranslateMap[DIK_WAKE] = EIK_WAKE;
		m_keyTranslateMap[DIK_WEBSEARCH] = EIK_WEBSEARCH;
		m_keyTranslateMap[DIK_WEBFAVORITES] = EIK_WEBFAVORITES;
		m_keyTranslateMap[DIK_WEBREFRESH] = EIK_WEBREFRESH;
		m_keyTranslateMap[DIK_WEBSTOP] = EIK_WEBSTOP;
		m_keyTranslateMap[DIK_WEBFORWARD] = EIK_WEBFORWARD;
		m_keyTranslateMap[DIK_WEBBACK] = EIK_WEBBACK;
		m_keyTranslateMap[DIK_MYCOMPUTER] = EIK_MYCOMPUTER;
		m_keyTranslateMap[DIK_MAIL] = EIK_MAIL;
		m_keyTranslateMap[DIK_MEDIASELECT] = EIK_MEDIASELECT;*/

		m_keyTranslateMap[EIMOUSEBUTTON_0] = EIMOUSEBUTTON_0;
		m_keyTranslateMap[EIMOUSEBUTTON_1] = EIMOUSEBUTTON_1;
		m_keyTranslateMap[EIMOUSEBUTTON_2] = EIMOUSEBUTTON_2;
		m_keyTranslateMap[EIMOUSEBUTTON_3] = EIMOUSEBUTTON_3;
		m_keyTranslateMap[EIMOUSEBUTTON_4] = EIMOUSEBUTTON_4;
		m_keyTranslateMap[EIMOUSEBUTTON_5] = EIMOUSEBUTTON_5;
		m_keyTranslateMap[EIMOUSEBUTTON_6] = EIMOUSEBUTTON_6;
		m_keyTranslateMap[EIMOUSEBUTTON_7] = EIMOUSEBUTTON_7;
	}

	WinMessagesInputSystem::~WinMessagesInputSystem(){
	}

	void WinMessagesInputSystem::initialize(boost::shared_ptr<InputInitParams> inputParams){
		m_winParams = boost::static_pointer_cast<WinMessagesInputInitParams>(inputParams);
		m_messageConnection = m_winParams->m_messageEvent->registerHandler(this,&WinMessagesInputSystem::recieveMessage);
	}

	void WinMessagesInputSystem::update(){
		/*RECT rect;
		GetWindowRect(m_winParams->m_hwnd,&rect);
		SetCursorPos(((rect.right-rect.left)/2)+rect.left,((rect.bottom-rect.top)/2)+rect.top);*/
	}

	void WinMessagesInputSystem::recieveMessage(MSG *message){
		int test;
		switch(message->message){
		case WM_MBUTTONDOWN:
			test = 0;
			break;
		case WM_MBUTTONUP:
			test = 1;
			break;
		case WM_LBUTTONDOWN:{
			m_bufferSwapMutex->lock();
			(*m_keyMapBackPtr)[EIMOUSEBUTTON_0].isPressed = true;
			(*m_keyMapBackPtr)[EIMOUSEBUTTON_0].wasPressed = false;
			m_bufferSwapMutex->unlock();

			// Inject into gui managers
			m_guiMgrMutex->lock();
			std::set<boost::shared_ptr<Graphics::GUIManager>>::iterator gui_itr = m_GUIManagers.begin();
			while(gui_itr != m_GUIManagers.end()){
				(*gui_itr)->injectKeyInput(EIMOUSEBUTTON_0,true);
				gui_itr++;
			}
			m_guiMgrMutex->unlock();
			break;
		}
		case WM_LBUTTONUP:{
			m_bufferSwapMutex->lock();
			(*m_keyMapBackPtr)[EIMOUSEBUTTON_0].isPressed = false;
			(*m_keyMapBackPtr)[EIMOUSEBUTTON_0].wasPressed = true;
			m_bufferSwapMutex->unlock();

			// Inject into gui managers
			m_guiMgrMutex->lock();
			std::set<boost::shared_ptr<Graphics::GUIManager>>::iterator gui_itr = m_GUIManagers.begin();
			while(gui_itr != m_GUIManagers.end()){
				(*gui_itr)->injectKeyInput(EIMOUSEBUTTON_0,false);
				gui_itr++;
			}
			m_guiMgrMutex->unlock();
			break;
		}
		case WM_RBUTTONDOWN:{
			m_bufferSwapMutex->lock();
			(*m_keyMapBackPtr)[EIMOUSEBUTTON_1].isPressed = true;
			(*m_keyMapBackPtr)[EIMOUSEBUTTON_1].wasPressed = false;
			m_bufferSwapMutex->unlock();

			// Inject into gui managers
			m_guiMgrMutex->lock();
			std::set<boost::shared_ptr<Graphics::GUIManager>>::iterator gui_itr = m_GUIManagers.begin();
			while(gui_itr != m_GUIManagers.end()){
				(*gui_itr)->injectKeyInput(EIMOUSEBUTTON_1,true);
				gui_itr++;
			}
			m_guiMgrMutex->unlock();
			break;
		}
		case WM_RBUTTONUP:{
			m_bufferSwapMutex->lock();
			(*m_keyMapBackPtr)[EIMOUSEBUTTON_1].isPressed = false;
			(*m_keyMapBackPtr)[EIMOUSEBUTTON_1].wasPressed = true;
			m_bufferSwapMutex->unlock();

			// Inject into gui managers
			m_guiMgrMutex->lock();
			std::set<boost::shared_ptr<Graphics::GUIManager>>::iterator gui_itr = m_GUIManagers.begin();
			while(gui_itr != m_GUIManagers.end()){
				(*gui_itr)->injectKeyInput(EIMOUSEBUTTON_1,false);
				gui_itr++;
			}
			m_guiMgrMutex->unlock();
			break;
		}
		case WM_MOUSEMOVE:
			m_bufferSwapMutex->lock();
			m_mouseDataBackPtr->xPos = message->pt.x;
			m_mouseDataBackPtr->yPos = message->pt.y;

			RECT rect;
			GetWindowRect(m_winParams->m_hwnd,&rect);
			m_mouseDataBackPtr->deltaX += message->pt.x - m_mouseXPos;//(((rect.right-rect.left)/2)+rect.left);
			m_mouseDataBackPtr->deltaY += message->pt.y - m_mouseYPos;//(((rect.bottom-rect.top)/2)+rect.top);

			m_mouseXPos = message->pt.x;
			m_mouseYPos = message->pt.y;
			m_bufferSwapMutex->unlock();
			break;
		case WM_KEYDOWN:{
			std::map<DWORD,KeyDefinition>::iterator itr = m_keyTranslateMap.find(message->wParam);
			if(itr == m_keyTranslateMap.end()){
				LOG_ERROR("Unknown key pressed");
				assert(0);
			}

			m_bufferSwapMutex->lock();
			(*m_keyMapBackPtr)[itr->second].isPressed = true;
			(*m_keyMapBackPtr)[itr->second].wasPressed = false;
			m_bufferSwapMutex->unlock();

			// Inject into gui managers
			m_guiMgrMutex->lock();
			std::set<boost::shared_ptr<Graphics::GUIManager>>::iterator gui_itr = m_GUIManagers.begin();
			while(gui_itr != m_GUIManagers.end()){
				(*gui_itr)->injectKeyInput(itr->second,true);
				gui_itr++;
			}
			m_guiMgrMutex->unlock();
			break;
		}
		case WM_KEYUP:{
			std::map<DWORD,KeyDefinition>::iterator itr = m_keyTranslateMap.find(message->wParam);
			if(itr == m_keyTranslateMap.end()){
				LOG_ERROR("Unknown key pressed");
				assert(0);
			}

			m_bufferSwapMutex->lock();
			(*m_keyMapBackPtr)[itr->second].isPressed = false;
			(*m_keyMapBackPtr)[itr->second].wasPressed = true;
			m_bufferSwapMutex->unlock();

			// Inject into gui managers
			m_guiMgrMutex->lock();
			std::set<boost::shared_ptr<Graphics::GUIManager>>::iterator gui_itr = m_GUIManagers.begin();
			while(gui_itr != m_GUIManagers.end()){
				(*gui_itr)->injectKeyInput(itr->second,false);
				gui_itr++;
			}
			m_guiMgrMutex->unlock();
			break;
		}
		}
	}
}